<template xmlns:v-contextmenu="http://www.w3.org/1999/xhtml">
  <div style="width: 100%; height: 100%; overflow: hidden;" :style="absoluteLayoutCanvasStyleObject">
    <div class="canvas-toolbar">
      <div class="float-left">

        <Poptip transfer trigger="click" placement="bottom"
                @on-popper-show="styleFilterSettingModalVisible = true"
                @on-popper-hide="styleFilterSettingModalVisible = false">
          <Tooltip transfer :content="'滤镜配置'" placement="bottom">
            <Button size="small" class="m-r-5px" type="primary"><Icon custom="iconfont icon-style-filter"/></Button>
          </Tooltip>
          <div slot="content">
            <StyleFilterSettingModal ></StyleFilterSettingModal>
          </div>
        </Poptip>

        <Tooltip transfer content="清空所有参考线" placement="bottom">
          <Button class="m-r-5px" size="small" type="primary" @click="clearReferenceLines">
            <Icon custom="iconfont iconclear-line" size="17"/>
          </Button>
        </Tooltip>

        <Tooltip transfer content="放大、缩小、自适应、还原100%" placement="bottom">
          <ButtonGroup size="small">
            <Button type="primary" @click="canvasZoomChange('zoomIn')"><Icon custom="iconfont iconzoomin" style="margin-top: -2px;"/></Button>
            <Button type="primary" @click="canvasZoomChange('zoomOut')"><Icon custom="iconfont iconzoomout" style="margin-top: -2px;"/></Button>
            <Button type="primary" @click="canvasZoomChange('zoomAuto')"><Icon custom="iconfont icon-zoom-auto" style="margin-top: -2px;"/></Button>
            <Button type="primary" @click="canvasZoomChange('zoomReset')"><Icon custom="iconfont iconsearch" style="margin-top: -2px;"/></Button>
            <Button type="default">{{ (zoomValue * 100).toFixed(0) }}%</Button>
          </ButtonGroup>
        </Tooltip>

        <LayoutItemSearch class="m-l-5px"></LayoutItemSearch>

        <!--<span class="color-white m-l-10px" v-show="canvasEnabled">
          <Tooltip content="画布被激活的状态下，即可将组件拖入画布中" :max-width="400">
            <Icon type="md-alert" size="13"/> <span class="m-l-5px" style="text-decoration: underline;">画布已激活组件放置事件</span>
          </Tooltip>
        </span>-->

      </div>
    </div>

    <div id="AbsoluteLayoutContainer" class="absolute-layout-container">
      <ZoomArea ref="zoomArea" :scale-value="zoomValue" @onZoomAreaClick="layoutCanvasClick">
        <div class="canvas-map"
             :style="{
               position: 'absolute',
               left: layout.layoutConfigData.widthPixelUnit == '%' ? '21px': '50px',
               top: layout.layoutConfigData.heightPixelUnit == '%' ? '21px': '50px',
               width: layout.layoutConfigData.width + layout.layoutConfigData.widthPixelUnit,
               height: layout.layoutConfigData.height + layout.layoutConfigData.heightPixelUnit
             }">
          <div class="canvas-map-layout-item"
               :class="buildLayoutItemActiveClass(layoutItem)"
               v-for="layoutItem in layout.layoutItems"
               :key="layoutItem.id"
               :style="{
                 position: 'absolute',
                 left: layoutItem.layoutItemConfigData.left + 'px',
                 top: layoutItem.layoutItemConfigData.top + 'px',
                 width: layoutItem.layoutItemConfigData.width + 'px',
                 height: layoutItem.layoutItemConfigData.height + 'px'
               }"></div>
          <div class="canvas-map-group-item"
               :class="buildGroupItemActiveClass(groupItem)"
               v-for="groupItem in layout.layoutGroup"
               :key="groupItem.id"
               :style="{
                 position: 'absolute',
                 left: groupItem.groupItemConfigData.left + 'px',
                 top: groupItem.groupItemConfigData.top + 'px',
                 width: groupItem.groupItemConfigData.width + 'px',
                 height: groupItem.groupItemConfigData.height + 'px'
               }"></div>
        </div>
        <div id="AbsoluteLayout"
             class="absolute-layout-canvas no-select"
             :class="buildLayoutClassObj(layout)"
             :style="Object.assign({
               transform: 'scale('+zoomValue+')',
               transformOrigin: '0 0',
               width: layout.layoutConfigData.width + layout.layoutConfigData.widthPixelUnit,
               height: layout.layoutConfigData.height + layout.layoutConfigData.heightPixelUnit,
               backgroundColor: layout.layoutConfigData.backgroundColor,
               outline: canvasEnabled ? (1 * 1/zoomValue) + 'px solid #4AFFFF': 'none',
               backgroundImage: layout.layoutConfigData.imageRelativePath ? 'url('+canvasBackgroundImageSrc+')': '',
               backgroundRepeat: layout.layoutConfigData.imageRelativePath ? layout.layoutConfigData.imageRepeat: '',
               backgroundSize: layout.layoutConfigData.imageRelativePath ? layout.layoutConfigData.imageSize: '',
               left: layout.layoutConfigData.widthPixelUnit == '%' ? '21px': '50px',
               top: layout.layoutConfigData.heightPixelUnit == '%' ? '21px': '50px'
             }, $PnUtil.cssToVueStyleObj(layout.layoutConfigData.customStyleCode))"
             @click.stop="layoutCanvasClick" @contextmenu.stop="onLayoutCanvasRightClickHandler">

          <Modal
              v-model="alongComponentConfigModalVisible"
              title="独立配置"
              :footer-hide="true">

          </Modal>

          <vue-draggable-resizable v-for="layoutItem in layout.layoutItems"
                                   :key="layoutItem.id"
                                   :id="'drag-'+layoutItem.id"
                                   class-name-handle="drag-handle-class"
                                   :draggable="layoutItem.layoutItemConfigData.draggableEnabled"
                                   :resizable="layoutItem.layoutItemConfigData.draggableEnabled"
                                   :parent="false"
                                   :scale="zoomValue"
                                   :grid="[layout.layoutConfigData.dragPixel, layout.layoutConfigData.dragPixel]"
                                   :x="layoutItem.layoutItemConfigData.left"
                                   :y="layoutItem.layoutItemConfigData.top"
                                   :w="layoutItem.layoutItemConfigData.width"
                                   :h="layoutItem.layoutItemConfigData.height"
                                   :style="{
                                       // zIndex: layoutItem.layoutItemConfigData.zIndex,
                                       zIndex: currentSelectLayoutItemId == layoutItem.id || currentSelectLayoutItemIds.indexOf(layoutItem.id) > -1 ? 8888 : layoutItem.layoutItemConfigData.zIndex,
                                       borderWidth: layoutItem.layoutItemConfigData.display == 'none' ? '0':undefined,
                                       pointerEvents: layoutItem.layoutItemConfigData.display == 'none' ? 'none':'auto',
                                       display: alongShowTargetIdList.length > 0 && alongShowTargetIdList.indexOf(layoutItem.id) < 0 ? 'none':undefined
                                     }"
                                   :layoutItem="layoutItem"
                                   :onResizeStart="onLayoutItemResizeStartCallback"
                                   @activated="onLayoutItemActivated(layoutItem)" @deactivated="onLayoutItemDeactivated"
                                   @dragging="onLayoutItemDrag" @dragstop="onLayoutItemDragStop"
                                   @resizing="onLayoutItemResize" @resizestop="onLayoutItemResizeStop">
            <div class="absolute-layout-item"
                 :class="buildLayoutItemActiveClass(layoutItem) + buildLayoutItemCustomClassName(layoutItem) + buildLayoutItemHiddenClassName(layoutItem)"
                 :style="{
                     perspective: layoutItem.layoutItemConfigData.use3dRotate ? layoutItem.layoutItemConfigData.perspectiveFor3d + 'px' : 'none',
                   }"
                 :id="layoutItem.id"
                 :data-id="layoutItem.id"
                 @click.stop="layoutItemClick(layoutItem, $event)"
                 @contextmenu.stop="onLayoutItemRightClickHandler($event, layoutItem.layoutItemConfigData, layoutItem.component)">

              <div class="w-h-full" :style="{transform: buildLayoutItem3dTransformStyleValue(layoutItem), opacity: layoutItem.layoutItemConfigData.opacity,}">
                <component :is="layoutItem.name" :layoutItemId="layoutItem.id" :toggleIsLoaded="layoutItem.component.id"
                           :style="{
                             display: layoutItem.layoutItemConfigData.display
                           }">
                  <FuncCompContainer :layout-item="layoutItem" :style="{filter: buildLayoutItemStyleFilter(layout.layoutConfigData)}">
                    <component v-if="layoutItem.component.id" :ref="layoutItem.component.id" :is="layoutItem.component.name" :location="layoutItem.id"></component>
                  </FuncCompContainer>
                </component>
              </div>

            </div>
          </vue-draggable-resizable>

          <vue-draggable-resizable
              :id="'drag-'+groupItem.id"
              class-name-handle="drag-handle-class"
              class="group-item"
              :title="groupItemEditable ? '双击可关闭编辑组内元素':'双击可编辑组内元素'"
              :ref="'groupItem-'+groupItem.id"
              v-for="groupItem in layout.layoutGroup"
              :key="groupItem.id"
              :draggable="groupItem.groupItemConfigData.draggable"
              :resizable="groupItem.groupItemConfigData.draggable"
              :parent="false"
              :scale="zoomValue"
              :grid="[layout.layoutConfigData.dragPixel, layout.layoutConfigData.dragPixel]"
              :x="groupItem.groupItemConfigData.left"
              :y="groupItem.groupItemConfigData.top"
              :w="groupItem.groupItemConfigData.width"
              :h="groupItem.groupItemConfigData.height"
              :style="{
                zIndex: calculateGroupItemShadeZIndex(groupItem),
                backgroundColor: groupItemEditable ? '': groupItem.groupItemConfigData.display == 'none' ? '':'rgba(0,0,0,0.1)',
                borderWidth: groupItem.groupItemConfigData.display == 'none' ? '0':undefined,
                pointerEvents: groupItem.groupItemConfigData.display == 'none' ? 'none':'auto',
                display: alongShowTargetIdList.length > 0 && alongShowTargetIdList.indexOf(groupItem.id) < 0 ? 'none':undefined
              }"
              :groupItem="groupItem"
              :handles="['mr','br','bm']"
              :onResizeStart="onGroupItemResizeStartCallback"
              @activated="onGroupItemActivated(groupItem)" @deactivated="onGroupItemDeactivated"
              @dragging="onGroupItemDrag" @dragstop="onGroupItemDragStop"
              @resizestop="onGroupItemResizeStop">
            <div class="group-item-child w-h-full"
                 :class="buildGroupItemActiveClass(groupItem)"
                 :id="groupItem.id"
                 @click.stop="groupItemClick(groupItem, $event)"
                 @dblclick="groupItemDblclick(groupItem)"
                 @contextmenu.stop="onGroupItemRightClickHandler($event, groupItem)">

              <div title="已被锁定"
                   v-show="groupItem.groupItemConfigData.draggable == false
                   && $store.state.designer.currentSelectGroupItemId == groupItem.id" class="lock-icon">
                <Icon :custom="'iconfont iconlock'"/>
              </div>

            </div>
          </vue-draggable-resizable>

        </div>
      </ZoomArea>

      <EnshrineCompFormModal ref="enshrineCompFormModal"
                             :show="enshrineCompFormModalVisible"
                             @cancel="enshrineCompFormModalVisible = false"></EnshrineCompFormModal>

      <Modal
          v-model="echartsChartOptionModalVisible"
          title="图表OPTION对象查询视窗"
          :footer-hide="true">
        <Alert show-icon>扩展脚本中添加的配置，不会在此显示出来</Alert>
        <div style="background-color: #fff;">

          <PnJsonEditor v-model="echartsChartOptionData"></PnJsonEditor>
        </div>
      </Modal>

      <SplitLayoutItemFormModal ref="SplitLayoutItemFormModal"></SplitLayoutItemFormModal>

      <v-contextmenu ref="layoutCanvasContextmenu">
        <v-contextmenu-item @click="layoutCanvasContextmenuClick('layoutCanvasMenu_clearCanvas')"><Icon custom="iconfont iconqingkong"/> 清空画布</v-contextmenu-item>
        <v-contextmenu-submenu title="粘贴剪切板中的组件">
          <v-contextmenu-item @click="layoutCanvasContextmenuClick('layoutCanvasMenu_pasteShearPlateData')"><Icon custom="iconfont icon-paste"/> 不携带位置配置</v-contextmenu-item>
          <v-contextmenu-item @click="layoutCanvasContextmenuClick('layoutCanvasMenu_pasteShearPlateDataRetainLocation')"><Icon custom="iconfont icon-paste"/> 携带位置配置</v-contextmenu-item>
        </v-contextmenu-submenu>

        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-item @click="layoutCanvasContextmenuClick('layoutCanvasMenu_logoutKeyDownAndUp')"><Icon type="md-close" size="14"/>注销所有键盘事件</v-contextmenu-item>
      </v-contextmenu>

      <v-contextmenu ref="contextmenu">
        <v-contextmenu-item v-show="contentMenuOption.unbindComponent" @click="layoutItemContextMenuClick('menu_unbindComponent')"><Icon custom="iconfont icon-unbind"/> 解绑关联组件</v-contextmenu-item>
        <v-contextmenu-item v-show="contentMenuOption.unbindComponent" divider></v-contextmenu-item>
        <!--<v-contextmenu-item @click="layoutItemContextMenuClick('menu_horizontalCenter')"><Icon custom="iconfont iconalign-center" /> 水平居中</v-contextmenu-item>-->
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_setTop')"><Icon custom="iconfont iconvertical-align-top" /> 置顶</v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_setDown')"><Icon custom="iconfont iconvertical-align-botto" /> 置底</v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_setTopOne')"><Icon custom="iconfont icon-top-one" /> 上移一层</v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_setDownOne')"><Icon custom="iconfont icon-down-one" /> 下移一层</v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_hide')"><Icon type="md-eye-off" size="14"/> 隐藏</v-contextmenu-item>
        <v-contextmenu-item v-show="currentSelectLayoutItemIds.length > 1 ? true : !contentMenuOption.layoutItemLockStatus"
                            @click="layoutItemContextMenuClick('menu_lock')"><Icon custom="iconfont iconlock" /> 锁定</v-contextmenu-item>
        <v-contextmenu-item v-show="currentSelectLayoutItemIds.length > 1 ? true : contentMenuOption.layoutItemLockStatus"  @click="layoutItemContextMenuClick('menu_unlock')"><Icon custom="iconfont iconunlock" /> 解锁</v-contextmenu-item>
        <v-contextmenu-item v-show="alongShowTargetIdList.length == 0" @click="layoutItemContextMenuClick('menu_alongShowEnter')"><Icon custom="iconfont icon-along-show" /> 单独显示图层</v-contextmenu-item>
        <v-contextmenu-item v-show="alongShowTargetIdList.length > 0" @click="layoutItemContextMenuClick('menu_alongShowCancel')"><Icon type="md-close-circle" size="14"/> 取消单独显示</v-contextmenu-item>
        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-submenu title="拆分布局块">
          <v-contextmenu-item @click="layoutItemContextMenuClick('menu_splitLayoutItem_h')"><Icon custom="iconfont icon-split-layout-item-h" /> 横向拆分</v-contextmenu-item>
          <v-contextmenu-item @click="layoutItemContextMenuClick('menu_splitLayoutItem_v')"><Icon custom="iconfont icon-split-layout-item-v" /> 纵向拆分</v-contextmenu-item>
        </v-contextmenu-submenu>
        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_createGroup')"><Icon custom="iconfont iconreferenceentitydefc" size="15" /> 组合</v-contextmenu-item>
        <v-contextmenu-submenu v-show="layoutGroup.length > 0 && contentMenuOption.showAddToLayoutGroupMenuItem" title="加入组合">
          <v-contextmenu-item v-for="groupItem in layoutGroup" :key="groupItem.id" @click="addLayoutItemsToGroupItem(groupItem.id)">
            {{groupItem.name ? groupItem.name : groupItem.id}}
          </v-contextmenu-item>
        </v-contextmenu-submenu>
        <v-contextmenu-item v-show="!contentMenuOption.showAddToLayoutGroupMenuItem" @click="shiftOutLayoutItemsFromGroupItem">
          <Icon custom="iconfont icon-shift-out-group" size="15" /> 移出组合</v-contextmenu-item>
        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_enshrine')"><Icon type="md-star" size="15"/> 收藏</v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_copyLayoutItem')"><Icon type="md-copy" size="15"/> 当前页复制</v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_crossPageCopyLayoutItem')"><Icon type="md-copy" size="15"/> 复制至剪切板</v-contextmenu-item>
        <v-contextmenu-submenu title="组件配置复制">
          <v-contextmenu-item @click="layoutItemContextMenuClick('menu_copyComponentConfigData')">复制关联组件的配置</v-contextmenu-item>
          <v-contextmenu-item @click="layoutItemContextMenuClick('menu_pasteComponentConfigData')">粘贴配置至关联组件</v-contextmenu-item>
        </v-contextmenu-submenu>
        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-item v-show="!isAlongCompEditModel" @click="layoutItemContextMenuClick('menu_alongCompEditModel')"><Icon custom="iconfont icon-duli"/> 独立编辑</v-contextmenu-item>
        <v-contextmenu-item @click="layoutItemContextMenuClick('menu_delLayoutItem')"><Icon type="md-trash" size="15"/> 删除布局块</v-contextmenu-item>
      </v-contextmenu>

      <v-contextmenu ref="groupItemContextmenu">
        <v-contextmenu-submenu title="组内元素">
          <v-contextmenu-item v-for="(layoutItem, index) in contentMenuOption.currentGroupAllLayoutItems" :key="index" @click="currentGroupAllLayoutItemsClickHandler(layoutItem)">
            <Icon custom="iconfont icon-layer" /> {{layoutItem | layoutItemAliasNameFilter}}
          </v-contextmenu-item>
        </v-contextmenu-submenu>
        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_setTop')"><Icon custom="iconfont iconvertical-align-top" /> 置顶</v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_setDown')"><Icon custom="iconfont iconvertical-align-botto" /> 置底</v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_hide')"><Icon type="md-eye-off" size="14"/> 隐藏</v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_reverseHide')"><Icon custom="iconfont icon-reverse-hide" size="15"/> 反选隐藏</v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_reverseShow')"><Icon custom="iconfont icon-reverse-show" size="15"/> 反选显示</v-contextmenu-item>
        <v-contextmenu-item v-show="currentSelectGroupItemIds.length > 1 ? true : !contentMenuOption.groupItemLockStatus"
                            @click="groupItemContextMenuClick('groupMenu_lock')"><Icon custom="iconfont iconlock" /> 锁定</v-contextmenu-item>
        <v-contextmenu-item v-show="currentSelectGroupItemIds.length > 1 ? true : contentMenuOption.groupItemLockStatus"
                            @click="groupItemContextMenuClick('groupMenu_unlock')"><Icon custom="iconfont iconunlock" /> 解锁</v-contextmenu-item>
        <v-contextmenu-item v-show="alongShowTargetIdList.length == 0" @click="groupItemContextMenuClick('groupMenu_alongShowEnter')"><Icon custom="iconfont icon-along-show" /> 单独显示图层</v-contextmenu-item>
        <v-contextmenu-item v-show="alongShowTargetIdList.length > 0" @click="groupItemContextMenuClick('groupMenu_alongShowCancel')"><Icon type="md-close-circle" size="14"/> 取消单独显示</v-contextmenu-item>
        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-item @click="groupItemDblclick">
          <Icon :custom="groupItemEditable ? 'iconfont icon-close-edit':'iconfont icon-open-edit'" size="12" /> {{groupItemEditable ? '取消':'打开'}}编辑状态
        </v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_undoGroupItem')"><Icon custom="iconfont icon-undo-group-item" size="12" /> 取消组合</v-contextmenu-item>
        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_enshrine')"><Icon type="md-star" size="15"/> 收藏</v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_copyGroupItem')"><Icon type="md-copy" size="15"/> 复制</v-contextmenu-item>
        <v-contextmenu-item divider></v-contextmenu-item>
        <v-contextmenu-item v-show="!isAlongCompEditModel" @click="groupItemContextMenuClick('groupMenu_alongCompEditModel')"><Icon custom="iconfont icon-duli"/> 独立编辑</v-contextmenu-item>
        <v-contextmenu-item @click="groupItemContextMenuClick('groupMenu_deleteGroupItem')"><Icon type="md-trash" size="15"/> 删除组</v-contextmenu-item>
      </v-contextmenu>

      <canvas id="canvas_map" :style="{bottom: canvasMapCollapsed ? '-3000px':'10px'}"></canvas>
    </div>
  </div>
</template>

<script>

import Vue from 'vue'
import _ from "lodash";

// 右键菜单组件
import contentmenu from 'v-contextmenu'
import '../../../../assets/css/contextmenu.css'
Vue.use(contentmenu);

import VueDraggableResizable from '../common/drag-resiza/vue-draggable-resizable'
import '../common/drag-resiza/vue-draggable-resizable.css'

import '../../../../utils/CanvasMap'

import FuncCompContainer from '../common/FuncCompContainer'
import VueRulerTool from './VueRulerTool'
import ZoomArea from "../common/ZoomArea";
import EnshrineCompFormModal from "../../admin/enshrineComp/EnshrineCompFormModal";
import StyleFilterSettingModal from '../common/StyleFilterSettingModal';
import LayoutItemSearch from '../common/LayoutItemSearch';
import SplitLayoutItemFormModal from '../common/SplitLayoutItemFormModal'

import AbsoluteLayoutGlobalMixin from '@/mixin/AbsoluteLayoutGlobalMixin'
import CanvasDesignerMixin from '@/mixin/CanvasDesignerMixin'

import '../../../../assets/css/drag-handle.css'

import { createHelpers } from 'vuex-map-fields';

const { mapFields } = createHelpers({
  getterType: 'designer/getField',
  mutationType: 'designer/updateField',
});

export default {
  name: 'AbsoluteLayoutCanvas',
  components: {
    FuncCompContainer,
    VueRulerTool,
    ZoomArea,
    EnshrineCompFormModal,
    StyleFilterSettingModal,
    LayoutItemSearch,
    SplitLayoutItemFormModal,
    VueDraggableResizable
  },
  mixins: [CanvasDesignerMixin, AbsoluteLayoutGlobalMixin],
  data() {
    return {
      echartsChartOptionModalVisible: false,
      echartsChartOptionData: null,

      tmpCurrentSelectLayoutItemId: '', // 临时存储当前选中布局块的ID

      $AbsoluteLayout: null, // 存储画布JQuery对象
      keydownFlag: false, // 用此变量来限制keydown事件在windows系统下无限触发的问题
      keepSelectable: false, // 标识当前是否保持按住alt按键，用于框选布局块时使用

      tmpCurrentSelectGroupItemId: '', // 临时存储当前选中组的ID
      currentSelectGroupItemLocation: {}, // 临时存储当前选中组的位置信息，当选中多个组的时候，会以组项ID作为Key，{left: value, top: value}作为值

      groupItemEditable: false, // 标识组是否可以编辑，双击组即可打开编辑状态

      dragShadowVisible: false, // 标识当前是否显示有拖拽阴影

      enshrineCompFormModalVisible: false,
      styleFilterSettingModalVisible: false,

      currentSelectGroupItemWhlt: {}, // 用于临时存储当前选中布局块的尺寸位置信息
      currentSelectLayoutItemWhlt: {}, // 用于临时存储当前选中布局块的尺寸位置信息

      contentMenuOption: {
        unbindComponent: true,
        layoutItemLockStatus: false,
        groupItemLockStatus: false,
        showAddToLayoutGroupMenuItem: false,
        currentGroupAllLayoutItems: []
      },

      alongComponentConfigModalVisible: false
    }
  },
  destroyed() {
    this.$EventBus.$off('pn_showLayoutCanvasContextmenu')
  },
  mounted() {
    this.$AbsoluteLayout = $('#AbsoluteLayout');

    // 设计器初始化之后先给画布的放置事件配置scope为compCardScope
    setTimeout(()=>{
      this.$AbsoluteLayout.droppable('option', 'scope', 'compCardScope');
    }, 100);

    this.registerWindowBeforeunload();
    this.registerCanvasDrop();
    this.registerLayoutItemDrop();
    this.registerKeyDownAndUp();
    this.registerCanvasNonactivated();

    this.$nextTick(() => {
      this.$store.commit('designer/setAbsoluteLayoutContainerWidth', $('#AbsoluteLayoutContainer').width());
      window.onresize = () => {
        this.$refs['zoomArea'].initRulerSize();
        this.$store.commit('designer/setAbsoluteLayoutContainerWidth', $('#AbsoluteLayoutContainer').width())
      };

      canvasmap(document.querySelector('#canvas_map'), {
        viewport: document.querySelector('#zoomArea'),
        interval: 50,
        styles: {
          // '.func-comp-container': 'rgba(0,0,0,0.3)',
          // '.absolute-layout-item.active': 'rgba(30,136,229,1)',
          // '.group-item-child.active': 'rgba(251,140,0,0.8)',
          // '.absolute-layout-canvas': 'rgba(121,85,72,0.3)'
          '.canvas-map': 'rgba(14,43,67,1)',
          '.canvas-map-layout-item': 'rgba(250,250,250,0.4)',
          '.canvas-map-layout-item.active': 'rgba(30,136,229,1)',
          '.canvas-map-group-item.active': 'rgba(251,140,0,0.8)',
        },
        back: '#616161',
        view: 'rgba(30,136,229,0.4)',
        drag: 'rgba(30,136,229,0.3)',
      });

      this.$EventBus.$on('pn_showLayoutCanvasContextmenu', (event) => {
        this.$refs.layoutCanvasContextmenu.show(this.$DesignerCommonUtil.calculateContextmenuPosition(
            event.pageX, event.pageY, this.$(this.$refs.layoutCanvasContextmenu.$el).outerHeight()
        ))
      })
    });

    this.$EventBus.$on('pn_showEchartsChartOption', (componentId)=>{
      if (this.$refs[componentId][0].chartOption) {
        this.echartsChartOptionModalVisible = !this.echartsChartOptionModalVisible;
        this.echartsChartOptionData = this.$refs[componentId][0].chartOption
      }else {
        this.$Message.error('查找不到相关图表的OPTION数据对象')
      }
    })

    this.$EventBus.$on('pn_reloadComponent', (componentId) => {
      this.reloadComponent(componentId)
    })

    this.initAllGroupItemShadeZIndex();
  },
  methods: {
    reloadComponent(componentId) {
      for(let i=0; i<this.layout.layoutItems.length; i++) {
        if(componentId == this.layout.layoutItems[i].component.id) {
          this.layout.layoutItems[i].component.id = ''
          this.$nextTick(()=>{
            this.layout.layoutItems[i].component.id = componentId
          })
        }
      }
    },

    /*************************组相关操作************************/

    /**
     * 计算组项遮罩层的层级zIndex
     */
    calculateGroupItemShadeZIndex (groupItem) {
      let zIndex = 0;
      if (this.groupItemEditable) {
        zIndex = -9999
      }else {
        if (this.currentSelectGroupItemId == groupItem.id || this.currentSelectGroupItemIds.indexOf(groupItem.id) > -1) {
          zIndex = 9999
        }else {
          for (let i=0; i<groupItem.layoutItemIds.length; i++) {
            let layoutItemZIndex = $('#drag-'+groupItem.layoutItemIds[i]).css('z-index');
            if (layoutItemZIndex) {
              let layoutItemZIndexNum = Number(layoutItemZIndex);
              if (layoutItemZIndexNum != 8888) {
                if (layoutItemZIndexNum >= zIndex) {
                  zIndex = layoutItemZIndexNum
                }
              }
            }else {
              zIndex = 9999;
              break
            }
          }
        }
      }
      return zIndex;
    },

    /**
     * 通过模拟画布点击，实现页面加载后即计算所有组项的遮罩层zIndex
     */
    initAllGroupItemShadeZIndex () {
      setTimeout(() => {
        this.$AbsoluteLayout.click()
      }, 100)
    },

    groupItemClick (groupItem, event) {
      // 设置画布激活状态为false
      this.$store.commit('designer/setCanvasEnabled', false);

      this.$refs.groupItemContextmenu.hide();
      this.$refs.layoutCanvasContextmenu.hide();

      if(this.$store.getters['designer/getKeepCtrl'] || this.keepSelectable) {
        let selectGroupItemIds = this.currentSelectGroupItemIds.concat();

        if(selectGroupItemIds.indexOf(groupItem.id) > -1) {
          for (let i=0; i<selectGroupItemIds.length; i++) {
            if(groupItem.id == selectGroupItemIds[i]) {
              if(selectGroupItemIds.length > 1) {
                selectGroupItemIds.splice(i, 1);
                i--
              }
            }
          }
        }else {
          selectGroupItemIds.pushNoRepeat(groupItem.id);
        }
        this.$store.commit('designer/setCurrentSelectGroupItemIds', selectGroupItemIds);
      } else {
        if(this.currentSelectGroupItemIds.indexOf(groupItem.id) == -1) {
          this.$store.commit('designer/setCurrentSelectGroupItemIds', []) // 清除ctrl选中的布局块
        }
      }

      this.$store.commit('designer/setCurrentSelectLayoutItemId', '');
      this.$store.commit('designer/setCurrentSelectLayoutItemIds', []);
    },

    groupItemDblclick () {
      if (this.groupItemEditable) {
        this.groupItemEditable = false
      }else {
        this.groupItemEditable = true
      }
    },

    onGroupItemResizeStartCallback (handle, ev) {
      this.currentSelectGroupItemWhlt = {
        left: parseInt(ev.target.offsetParent.innerText.split(',')[0]),
        top: parseInt(ev.target.offsetParent.innerText.split(',')[1].replace(' ', '')),
        width: ev.target.offsetParent.offsetWidth,
        height: ev.target.offsetParent.offsetHeight
      };
    },

    onGroupItemActivated (groupItem) {
      this.registerKeyDownAndUp(); // 重新注册键盘监听

      this.tmpCurrentSelectGroupItemId = groupItem.id;
      this.$store.commit('designer/setCurrentSelectGroupItemId', groupItem.id);

      this.currentSelectGroupItemLocation[groupItem.id] = {
        left: this.$refs['groupItem-'+groupItem.id][0].x,
        top: this.$refs['groupItem-'+groupItem.id][0].y
      };

      this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');

      // let tmpGroupItem = this.$store.getters['designer/getLayoutGroupItemById'](groupItem.id);
      // tmpGroupItem.layoutItemIds.forEach(layoutItemId => {
      //   $('#'+layoutItemId).css('border', '1px dotted red')
      // })
    },

    onGroupItemDeactivated () {

      this.tmpCurrentSelectGroupItemId = '';

      // 此处关闭右键菜单要设置一段延时，否则在布局块失活时，同步关闭菜单的话，会出现菜单点击无效的情况
      setTimeout(() => {
        this.$refs.groupItemContextmenu.hide()
      }, 150)
    },

    onGroupItemDrag (left, top) {
      // 拖拽过程生成初始位置的拖拽阴影
      /*if (!this.dragShadowVisible) {
        let $current = $('#drag-'+this.tmpCurrentSelectGroupItemId);
        let dragShadowDiv = "<div " +
          "id='dragShadowDiv' " +
          "style='position: absolute; left: "+left+"px; top: "+top+"px; width: "+$current.css('width')+"; height: "+$current.css('height')+"; background-color: #00CCFF; opacity: 0.1; z-index: 0;'></div>"
        this.$AbsoluteLayout.append(dragShadowDiv);
        this.dragShadowVisible = true;
      }*/

      // 这段代码是为了在多选多个组的时候，同步移动其他组
      if (this.currentSelectGroupItemIds.length > 0) {
        let currentGroupItem = this.$store.getters['designer/getLayoutGroupItemById'](this.tmpCurrentSelectGroupItemId);

        let offsetLeft = left - currentGroupItem.groupItemConfigData.left; // 左偏移
        let offsetTop = top - currentGroupItem.groupItemConfigData.top; // 上偏移

        let currentSelectGroupItemIds = this.currentSelectGroupItemIds;
        if (currentSelectGroupItemIds.length > 0) {
          currentSelectGroupItemIds.forEach(id => {
            if (id != this.tmpCurrentSelectGroupItemId) {
              let otherGroupItem = this.$store.getters['designer/getLayoutGroupItemById'](id);
              let otherLeft = otherGroupItem.groupItemConfigData.left + offsetLeft;
              let otherTop = otherGroupItem.groupItemConfigData.top + offsetTop;
              $('#drag-'+id).css('transform', 'translate('+otherLeft+'px, '+otherTop+'px)');
            }
          });
        }
      }
      // 这段代码是为了在多选多个组的时候，同步移动其他组 end

    },

    onGroupItemDragStop (left, top) {
      // 拖拽停止的时候，删除拖拽阴影DIV
      /*if (this.dragShadowVisible) {
        this.dragShadowVisible = false;
        $('#dragShadowDiv').remove();
      }*/

      // 同步移动组内关联的布局块
      let syncMoveLayoutItems = (layoutItemIds, offsetLeft, offsetTop) => {
        layoutItemIds.forEach(layoutItemId => {
          this.$store.commit('designer/setLayoutItemLeftAndTopOffset', {
            id: layoutItemId,
            direction: 'left',
            offset: offsetLeft
          });
          this.$store.commit('designer/setLayoutItemLeftAndTopOffset', {
            id: layoutItemId,
            direction: 'top',
            offset: offsetTop
          });
        });
      };

      let currentGroupItem = this.$store.getters['designer/getLayoutGroupItemById'](this.tmpCurrentSelectGroupItemId);

      let offsetLeft = left - currentGroupItem.groupItemConfigData.left; // 左偏移
      let offsetTop = top - currentGroupItem.groupItemConfigData.top; // 右偏移

      syncMoveLayoutItems(currentGroupItem.layoutItemIds, offsetLeft, offsetTop);
      this.$store.commit('designer/setGroupItemLeftAndTop', {id: this.tmpCurrentSelectGroupItemId, left: left, top: top});

      let currentSelectGroupItemIds = this.currentSelectGroupItemIds;
      if (currentSelectGroupItemIds.length > 0) {
        currentSelectGroupItemIds.forEach(id => {
          if (id != this.tmpCurrentSelectGroupItemId) {
            let otherGroupItem = this.$store.getters['designer/getLayoutGroupItemById'](id);
            syncMoveLayoutItems(otherGroupItem.layoutItemIds, offsetLeft, offsetTop);
            this.$store.commit('designer/setGroupItemLeftAndTop',
                {id: id, left: otherGroupItem.groupItemConfigData.left + offsetLeft, top: otherGroupItem.groupItemConfigData.top + offsetTop});
          }
        });
      }

    },

    onGroupItemResizeStop (left, top, width, height) {
      this.$store.commit('designer/setGroupItemWhlt', {
        id: this.tmpCurrentSelectGroupItemId,
        width: width,
        height: height,
        left: left,
        top: top
      });

      let currentGroupItem = this.$store.getters['designer/getLayoutGroupItemById'](this.tmpCurrentSelectGroupItemId);
      let layoutItemIds = currentGroupItem.layoutItemIds;

      let offsetLeft = left - this.currentSelectGroupItemWhlt.left;
      let offsetTop = top - this.currentSelectGroupItemWhlt.top;
      let offsetWidth = width - this.currentSelectGroupItemWhlt.width;
      let offsetHeight = height - this.currentSelectGroupItemWhlt.height;
      layoutItemIds.forEach(id => {
        this.$store.commit('designer/setLayoutItemWhltOffsetFromGroupResize', {
          id: id,
          offsetLeft: offsetLeft,
          offsetTop: offsetTop,
          offsetWidth: offsetWidth,
          offsetHeight: offsetHeight,
          originalGroupItemWhlt: {
            left: this.currentSelectGroupItemWhlt.left,
            top: this.currentSelectGroupItemWhlt.top,
            width: this.currentSelectGroupItemWhlt.width,
            height: this.currentSelectGroupItemWhlt.height
          }
        })
      });

      this.$DesignerCommonUtil.updateGroupItemStoreSize(this.tmpCurrentSelectGroupItemId)
    },

    currentGroupAllLayoutItemsClickHandler (layoutItem) {
      this.groupItemDblclick()
      this.onLayoutItemActivated(layoutItem)
      this.layoutItemClick(layoutItem)
      if (layoutItem.component.id) {
        this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', layoutItem.component.name + 'Form');
      }
    },

    onGroupItemRightClickHandler (e, groupItem) {
      e.preventDefault()
      if (this.currentSelectGroupItemId || this.currentSelectGroupItemIds.length > 0) {
        this.contentMenuOption.groupItemLockStatus = !groupItem.groupItemConfigData.draggable

        this.contentMenuOption.currentGroupAllLayoutItems = _.filter(this.layout.layoutItems, function (layoutItem) {
          return groupItem.layoutItemIds.indexOf(layoutItem.id) > -1
        })

        this.$refs.groupItemContextmenu.show(this.$DesignerCommonUtil.calculateContextmenuPosition(e.pageX, e.pageY, this.$(this.$refs.groupItemContextmenu.$el).outerHeight()))
      }
    },

    /**
     * 组项右键菜单点击事件处理
     * @param name
     */
    groupItemContextMenuClick (name) {
      let groupItemIds = _.compact(_.union([this.currentSelectGroupItemId], this.currentSelectGroupItemIds.concat()));

      switch (name) {
        case 'groupMenu_setTop':
          this.$DesignerCommonUtil.groupItemSetTop(groupItemIds);
          break;
        case 'groupMenu_setDown':
          this.$DesignerCommonUtil.groupItemSetDown(groupItemIds);
          break;
        case 'groupMenu_hide':
          this.$DesignerCommonUtil.groupItemHide(groupItemIds);
          break;
        case 'groupMenu_reverseHide':
          this.$DesignerCommonUtil.groupItemReverseHideOrShow(groupItemIds, true);
          break;
        case 'groupMenu_reverseShow':
          this.$DesignerCommonUtil.groupItemReverseHideOrShow(groupItemIds, false);
          break;
        case 'groupMenu_lock':
          this.$DesignerCommonUtil.groupItemLock(groupItemIds);
          break;
        case 'groupMenu_unlock':
          this.$DesignerCommonUtil.groupItemUnLock(groupItemIds);
          break;
        case 'groupMenu_alongShowEnter':
          this.$DesignerCommonUtil.toggleAlongShowLayout('groupItems', groupItemIds, 'enter')
          break;
        case 'groupMenu_alongShowCancel':
          this.$DesignerCommonUtil.toggleAlongShowLayout('groupItems', groupItemIds, 'cancel')
          break;
        case 'groupMenu_undoGroupItem':
          this.$DesignerCommonUtil.groupItemUndo(groupItemIds);
          break;
        case 'groupMenu_enshrine':
          var groupItem = this.$store.getters['designer/getLayoutGroupItemById'](this.currentSelectGroupItemId);
          var obj = {
            groupItemObj: groupItem,
            layoutItemObjs: []
          };
          groupItem.layoutItemIds.forEach(layoutItemId => {
            let layoutItem = this.$store.getters['designer/getLayoutItemById'](layoutItemId);
            obj.layoutItemObjs.push(layoutItem)
          });
          this.$refs.enshrineCompFormModal.formData.thumbnail_uri = 'image/group-image.png';
          this.$refs.enshrineCompFormModal.formData.type = 'G';
          this.$refs.enshrineCompFormModal.formData.layout_item_obj = JSON.stringify(obj);
          this.$refs.enshrineCompFormModal.formData.component_name = 'GroupItem';
          this.enshrineCompFormModalVisible = true;
          break;
        case 'groupMenu_copyGroupItem':
          this.$DesignerCommonUtil.groupItemCopy(groupItemIds);
          break;
        case 'groupMenu_deleteGroupItem':
          this.$DesignerCommonUtil.groupItemDelete(groupItemIds);
          break;
        case 'groupMenu_alongCompEditModel':
          this.$DesignerCommonUtil.toggleAlongCompEditModel(true, this.pageMetadata.id, [], groupItemIds)
          break;
        default:
      }

    },

    /*************************组相关操作 end ************************/


    /*************************工具条相关操作************************/

    clearReferenceLines () {
      this.$Modal.confirm({
        title: '提醒',
        content: '确定删除当前页面的参考线吗？',
        onOk: () => {
          this.$refs['zoomArea'].clearAllLines()
        }
      });
    },

    /*************************工具条相关操作 end ************************/

    onLayoutItemRightClickHandler (e, layoutItemConfigData, component) {
      e.preventDefault()
      if (this.currentSelectLayoutItemId || this.currentSelectLayoutItemIds.length > 0) {
        this.contentMenuOption.layoutItemLockStatus = !layoutItemConfigData.draggableEnabled
        // 这里判断一下当前所选中的布局块中是否被成组
        if (this.$DesignerCommonUtil.affirmLayoutItemsByGroup(this.layoutGroup,
            this.currentSelectLayoutItemIds.length > 0 ? this.currentSelectLayoutItemIds : [this.currentSelectLayoutItemId])) {
          this.contentMenuOption.showAddToLayoutGroupMenuItem = false
        }else {
          this.contentMenuOption.showAddToLayoutGroupMenuItem = true
        }
        if (!component.id) {
          this.contentMenuOption.unbindComponent = false
        }else {
          this.contentMenuOption.unbindComponent = true
        }
        this.$refs.contextmenu.show(this.$DesignerCommonUtil.calculateContextmenuPosition(e.pageX, e.pageY, this.$(this.$refs.contextmenu.$el).outerHeight()))
      }
    },

    /**
     * 布局块右键菜单点击事件处理
     * @param name
     */
    layoutItemContextMenuClick (name) {
      let layoutItemIds = _.compact(_.union([this.currentSelectLayoutItemId], this.currentSelectLayoutItemIds.concat()));

      switch (name) {
        case 'menu_delLayoutItem':
          this.$DesignerCommonUtil.layoutItemDelete(layoutItemIds);
          break;
        case 'menu_unbindComponent':
          this.$Modal.confirm({
            title: '提醒',
            content: '确认解除所选中布局块的关联组件吗？',
            onOk: () => {
              layoutItemIds.forEach(id => {
                this.$store.commit('designer/deleteComponentByLayoutItemId', id);
                this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '')
              });
            }
          });
          break;
        case 'menu_enshrine':
          var layoutItem = this.$store.getters['designer/getLayoutItemById'](this.currentSelectLayoutItemId);
          this.$refs.enshrineCompFormModal.formData.thumbnail_uri =
              JSON.parse(localStorage.getItem('allCompinfoObj'))[layoutItem.component.name].thumbnail_uri;
          this.$refs.enshrineCompFormModal.formData.type = 'F';
          this.$refs.enshrineCompFormModal.formData.layout_item_obj = JSON.stringify(layoutItem);
          this.$refs.enshrineCompFormModal.formData.component_name = layoutItem.component.name;
          this.enshrineCompFormModalVisible = true;
          break;
        case 'menu_copyLayoutItem':
          this.$DesignerCommonUtil.layoutItemCopy(layoutItemIds);
          break;
        case 'menu_crossPageCopyLayoutItem':
          this.$DesignerCommonUtil.layoutItemCopyToPage(layoutItemIds)
          break;
        case 'menu_copyComponentConfigData':
          this.$DesignerCommonUtil.copyComponentConfigData(this.currentSelectLayoutItemId)
          break;
        case 'menu_pasteComponentConfigData':
          this.$DesignerCommonUtil.pasteComponentConfigData(layoutItemIds)
          break;
        case 'menu_setTop':
          this.$DesignerCommonUtil.layoutItemSetTop(layoutItemIds);
          break;
        case 'menu_setDown':
          this.$DesignerCommonUtil.layoutItemSetDown(layoutItemIds);
          break;
        case 'menu_setTopOne':
          this.$DesignerCommonUtil.layoutItemSetTopOne(layoutItemIds);
          break;
        case 'menu_setDownOne':
          this.$DesignerCommonUtil.layoutItemSetDownOne(layoutItemIds);
          break;
        case 'menu_hide':
          this.$DesignerCommonUtil.layoutItemHide(layoutItemIds);
          break;
        case 'menu_createGroup':
          this.$DesignerCommonUtil.layoutItemCreateGroup(this.layoutGroup, layoutItemIds)
          break;
        case 'menu_splitLayoutItem_h':
          this.$refs['SplitLayoutItemFormModal'].init('h', this.currentSelectLayoutItemId)
          break;
        case 'menu_splitLayoutItem_v':
          this.$refs['SplitLayoutItemFormModal'].init('v', this.currentSelectLayoutItemId)
          break;
        case 'menu_lock':
          this.$DesignerCommonUtil.layoutItemLock(layoutItemIds);
          break;
        case 'menu_unlock':
          this.$DesignerCommonUtil.layoutItemUnLock(layoutItemIds);
          break;
        case 'menu_alongShowEnter':
          this.$DesignerCommonUtil.toggleAlongShowLayout('layoutItems', layoutItemIds, 'enter')
          break;
        case 'menu_alongShowCancel':
          this.$DesignerCommonUtil.toggleAlongShowLayout('layoutItems', layoutItemIds, 'cancel')
          break;
        case 'menu_alongCompEditModel':
          this.$DesignerCommonUtil.toggleAlongCompEditModel(true, this.pageMetadata.id, layoutItemIds, [])
          break;
        default:
      }
    },

    addLayoutItemsToGroupItem (groupItemId) {
      let layoutItemIds = this.currentSelectLayoutItemIds.length > 0 ? this.currentSelectLayoutItemIds : [this.currentSelectLayoutItemId]
      if(this.$DesignerCommonUtil.affirmLayoutItemsByGroup(this.layoutGroup, layoutItemIds)) {
        this.$Message.error({
          content: '选中项中存在已被成组的布局块，请重新选择',
          duration: 5
        })
      }else {
        this.$store.commit('designer/addLayoutItemsToGroupItem', {
          targetGroupItemId: groupItemId,
          newLayoutItemIds: layoutItemIds
        })
        this.$DesignerCommonUtil.updateGroupItemStoreSize(groupItemId)
      }
    },

    shiftOutLayoutItemsFromGroupItem () {
      let layoutItemIds = this.currentSelectLayoutItemIds.length > 0 ? this.currentSelectLayoutItemIds : [this.currentSelectLayoutItemId]
      // 判断当前所选的布局块中都属于哪些组
      let targetGroupItemIds = [];
      layoutItemIds.forEach(layoutItemId => {
        let targetGroupItemId = this.$DesignerCommonUtil.getLayoutItemBelongGroupItemId(layoutItemId, this.layoutGroup)
        if (targetGroupItemIds.indexOf(targetGroupItemId) < 0) {
          targetGroupItemIds.push(targetGroupItemId)
        }
      })
      // 判断当前所选的布局块中都属于哪些组 end
      targetGroupItemIds.forEach(groupItemId => {
        this.$store.commit('designer/shiftOutLayoutItemsFromGroupItem', {
          targetGroupItemId: groupItemId,
          layoutItemIds: layoutItemIds
        })
        this.$DesignerCommonUtil.updateGroupItemStoreSize(groupItemId)
      })
    },

    onLayoutItemActivated (layoutItem) {
      // console.log('onLayoutItemActivated');

      this.registerKeyDownAndUp(); // 重新注册键盘监听

      this.tmpCurrentSelectLayoutItemId = layoutItem.id;

      // 点击布局块的时候，清空画布的scope，然后给布局块设置droppable的属性scope为compCardScope，
      // 与组件库拖拽对象的scope对应，这样组件库的拖拽对象就可以放置在当前点击的布局块里
      this.$AbsoluteLayout.droppable('option', 'scope', '');
      $('.absolute-layout-item').droppable('option', 'scope', '');
      $('#'+layoutItem.id).droppable('option', 'scope', 'compCardScope');

      // 如果当前点击的布局块不等于store中存储的currentSelectLayoutItemId，就清空功能组件配置表单
      // (这一段代码是为了解决点击同一个布局块，会刷新功能组件表单的问题)
      if (this.$store.state.designer.currentSelectLayoutItemId != this.tmpCurrentSelectLayoutItemId) {
        this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');
      }

      this.$store.commit('designer/setCurrentSelectLayoutItemId', this.tmpCurrentSelectLayoutItemId);

    },

    onLayoutItemResizeStartCallback (handle, ev) {
      if(this.$store.state.designer.currentSelectLayoutItemIds.length > 0) {
        this.currentSelectLayoutItemWhlt = {
          left: parseInt(ev.target.offsetParent.innerText.split(',')[0]),
          top: parseInt(ev.target.offsetParent.innerText.split(',')[1].replace(' ', '')),
          width: ev.target.offsetParent.offsetWidth,
          height: ev.target.offsetParent.offsetHeight
        };
      }
    },

    onLayoutItemDeactivated () {
      // console.log('onLayoutItemDeactivated');
      this.tmpCurrentSelectLayoutItemId = '';

      // 此处关闭右键菜单要设置一段延时，否则在布局块失活时，同步关闭菜单的话，会出现菜单点击无效的情况
      setTimeout(item => {
        this.$refs.contextmenu.hide()
      }, 150)
    },

    onLayoutItemDrag (left, top) {

      // 拖拽过程生成初始位置的拖拽阴影
      /*if (!this.dragShadowVisible) {
        let $current = $('#drag-'+this.tmpCurrentSelectLayoutItemId);
        if (!$current.hasClass('h-center') && !$current.hasClass('v-center') && !$current.hasClass('h-v-center') && !$current.hasClass('h-r')) {
          let dragShadowDiv = "<div " +
            "id='dragShadowDiv' " +
            "style='position: absolute; left: "+left+"px; top: "+top+"px; width: "+$current.css('width')+"; height: "+$current.css('height')+"; background-color: #00CCFF; opacity: 0.1; z-index: 0;'></div>"
          this.$AbsoluteLayout.append(dragShadowDiv);
          this.dragShadowVisible = true;
        }
      }*/

      // 这段代码是为了在多选多个布局块的时候，同步移动其他布局块
      if (this.$store.state.designer.currentSelectLayoutItemIds.length > 0) {
        let currentLayoutItem = this.$store.getters['designer/getLayoutItemById'](this.tmpCurrentSelectLayoutItemId);

        let offsetLeft = left - currentLayoutItem.layoutItemConfigData.left; // 左偏移
        let offsetTop = top - currentLayoutItem.layoutItemConfigData.top; // 右偏移

        let currentSelectLayoutItemIds = this.$store.state.designer.currentSelectLayoutItemIds;
        if (currentSelectLayoutItemIds.length > 0) {
          currentSelectLayoutItemIds.forEach(id => {
            if (id != this.tmpCurrentSelectLayoutItemId) {
              let otherLayoutItem = this.$store.getters['designer/getLayoutItemById'](id);
              let otherLeft = otherLayoutItem.layoutItemConfigData.left + offsetLeft;
              let otherTop = otherLayoutItem.layoutItemConfigData.top + offsetTop;
              $('#drag-'+id).css('transform', 'translate('+otherLeft+'px, '+otherTop+'px)');
            }
          });
        }
      }
      // 这段代码是为了在多选多个布局块的时候，同步移动其他布局块 end
    },

    onLayoutItemDragStop (left, top) {
      // 拖拽停止的时候，删除拖拽阴影DIV
      /*if (this.dragShadowVisible) {
        this.dragShadowVisible = false;
        $('#dragShadowDiv').remove();
      }*/

      let currentLayoutItem = this.$store.getters['designer/getLayoutItemById'](this.tmpCurrentSelectLayoutItemId);
      let offsetLeft = left - currentLayoutItem.layoutItemConfigData.left; // 左偏移
      let offsetTop = top - currentLayoutItem.layoutItemConfigData.top; // 右偏移

      this.$store.commit('designer/setLayoutItemLeftAndTop', {id: this.tmpCurrentSelectLayoutItemId, left: left, top: top});

      // 如果多选了布局块，那么同步移动其他布局块
      let stayUpdateGroupItemIds = [];
      let currentSelectLayoutItemIds = this.$store.state.designer.currentSelectLayoutItemIds;
      if (currentSelectLayoutItemIds.length > 0) {
        currentSelectLayoutItemIds.forEach(id => {
          let groupItemId = this.$DesignerCommonUtil.getLayoutItemBelongGroupItemId(id, this.layoutGroup);
          if (groupItemId) {
            stayUpdateGroupItemIds.push(groupItemId)
          }
          if (id != this.tmpCurrentSelectLayoutItemId) {
            let otherLayoutItem = this.$store.getters['designer/getLayoutItemById'](id);
            this.$store.commit('designer/setLayoutItemLeftAndTop',
                {id: id, left: otherLayoutItem.layoutItemConfigData.left + offsetLeft, top: otherLayoutItem.layoutItemConfigData.top + offsetTop});
          }
        });
      }else {
        stayUpdateGroupItemIds.push(this.$DesignerCommonUtil.getLayoutItemBelongGroupItemId(this.tmpCurrentSelectLayoutItemId, this.layoutGroup))
      }

      stayUpdateGroupItemIds.forEach(groupItemId => {
        this.$DesignerCommonUtil.updateGroupItemStoreSize(groupItemId);
      })
    },

    onLayoutItemResize (left, top, width, height) {

      // 这段代码是为了在多选多个布局块的时候，同步调整其他布局块尺寸
      if (this.$store.state.designer.currentSelectLayoutItemIds.length > 0) {
        let currentLayoutItem = this.$store.getters['designer/getLayoutItemById'](this.tmpCurrentSelectLayoutItemId);

        let offsetLeft = left - this.currentSelectLayoutItemWhlt.left;
        let offsetTop = top - this.currentSelectLayoutItemWhlt.top;
        let offsetWidth = width - currentLayoutItem.layoutItemConfigData.width;
        let offsetHeight = height - currentLayoutItem.layoutItemConfigData.height;

        let currentSelectLayoutItemIds = this.$store.state.designer.currentSelectLayoutItemIds;
        if (currentSelectLayoutItemIds.length > 0) {
          currentSelectLayoutItemIds.forEach(id => {
            if (id != this.tmpCurrentSelectLayoutItemId) {
              let otherLayoutItem = this.$store.getters['designer/getLayoutItemById'](id);
              let otherLeft = otherLayoutItem.layoutItemConfigData.left + offsetLeft;
              let otherTop = otherLayoutItem.layoutItemConfigData.top + offsetTop;
              let otherWidth = otherLayoutItem.layoutItemConfigData.width + offsetWidth;
              let otherHeight = otherLayoutItem.layoutItemConfigData.height + offsetHeight;
              $('#drag-'+id).css('transform', 'translate('+otherLeft+'px, '+otherTop+'px)');
              $('#drag-'+id).css('width', otherWidth + 'px');
              $('#drag-'+id).css('height', otherHeight + 'px');
            }
          });
        }
      }
      // 这段代码是为了在多选多个布局块的时候，同步调整其他布局块尺寸 end

    },

    onLayoutItemResizeStop (left, top, width, height) {
      // console.log('onLayoutItemResizeStop');
      this.$store.commit('designer/setLayoutItemWhlt',
          {id: this.tmpCurrentSelectLayoutItemId, width: width, height: height, left: left, top: top});

      // 如果多选了布局块，那么同步调整其他布局块的尺寸和位置信息
      let stayUpdateGroupItemIds = [];
      let currentSelectLayoutItemIds = this.$store.state.designer.currentSelectLayoutItemIds;
      if (currentSelectLayoutItemIds.length > 0) {
        let offsetLeft = left - this.currentSelectLayoutItemWhlt.left;
        let offsetTop = top - this.currentSelectLayoutItemWhlt.top;
        let offsetWidth = width - this.currentSelectLayoutItemWhlt.width;
        let offsetHeight = height - this.currentSelectLayoutItemWhlt.height;
        currentSelectLayoutItemIds.forEach(id => {
          let groupItemId = this.$DesignerCommonUtil.getLayoutItemBelongGroupItemId(id, this.layoutGroup);
          if (groupItemId) {
            stayUpdateGroupItemIds.push(groupItemId)
          }
          if (id != this.tmpCurrentSelectLayoutItemId) {
            this.$store.commit('designer/setLayoutItemWhltOffset', {
              id: id,
              offsetLeft: offsetLeft,
              offsetTop: offsetTop,
              offsetWidth: offsetWidth,
              offsetHeight: offsetHeight
            })
          }
        });
      }else {
        stayUpdateGroupItemIds.push(this.$DesignerCommonUtil.getLayoutItemBelongGroupItemId(this.tmpCurrentSelectLayoutItemId, this.layoutGroup))
      }

      stayUpdateGroupItemIds.forEach(groupItemId => {
        this.$DesignerCommonUtil.updateGroupItemStoreSize(groupItemId);
      })
    },

    /**
     * 激活布局块框选监听
     */
    enableLayoutItemSelectable () {
      let $zoomAreaContainer = this.$('#zoomAreaContainer');
      let _this = this;
      if($zoomAreaContainer.selectable()) {
        $zoomAreaContainer.selectable("enable");
      }

      $zoomAreaContainer.selectable({
        filter: ".absolute-layout-item:not(.hidden)",
        start: function(event, ui) {
          _this.keepSelectable = true;
        },
        selected: function(event, ui) {
          let excludeLayoutItems = [];
          _this.layoutGroup.forEach(groupItem => {
            excludeLayoutItems = excludeLayoutItems.concat(groupItem.layoutItemIds)
          });// 排除已被成组的布局块
          let ids = [];
          let selectedDoms = $zoomAreaContainer.find('.absolute-layout-item.ui-selected');
          for(let i = 0; i<selectedDoms.length; i++){
            if (excludeLayoutItems.indexOf(selectedDoms[i].id) < 0) {
              ids.pushNoRepeat(selectedDoms[i].id)
            }else {
              $zoomAreaContainer.find('div#'+selectedDoms[i].id).removeClass('ui-selected')
            }
          }
          _this.$store.commit('designer/setCurrentSelectLayoutItemIds', ids);
          _this.$store.commit('designer/setCurrentSelectGroupItemIds', []);
        }
      });
    },

    /**
     * 激活组项框选监听
     */
    enableGroupItemSelectable () {
      let $zoomAreaContainer = this.$('#zoomAreaContainer');
      let _this = this;
      if($zoomAreaContainer.selectable()) {
        $zoomAreaContainer.selectable("enable");
      }

      $zoomAreaContainer.selectable({
        filter: ".group-item-child",
        start: function(event, ui) {
          _this.keepSelectable = true;
        },
        selected: function(event, ui) {
          let ids = [];
          let selectedDoms = $zoomAreaContainer.find('.group-item-child.ui-selected');
          for(let i = 0; i<selectedDoms.length; i++){
            ids.pushNoRepeat(selectedDoms[i].id);
            _this.currentSelectGroupItemLocation[selectedDoms[i].id] = {
              left: _this.$refs['groupItem-'+selectedDoms[i].id][0].x,
              top: _this.$refs['groupItem-'+selectedDoms[i].id][0].y
            };
          }
          _this.$store.commit('designer/setCurrentSelectGroupItemIds', ids);
          _this.$store.commit('designer/setCurrentSelectLayoutItemIds', []);
        }
      });
    },

    /**
     * 注销画布框选监听
     */
    disableSelectable () {
      this.$('#zoomAreaContainer').selectable("disable");
      this.keepSelectable = false;
    },

    /**
     * 注册画布失活监听
     */
    registerCanvasNonactivated () {
      let func = () => {
        $(document).unbind('keydown');
        $(document).unbind('keyup');
        this.registerKeyCtrlAndS(); // 重新再注册ctrl + s键监听
      };
      this.$EventBus.$on('pn_headerClick', func);
      this.$EventBus.$on('pn_footerClick', func);
      // this.$EventBus.$on('pn_leftSidebarClick', func);
      this.$EventBus.$on('pn_rightSidebarClick', func);
    },

    /**
     * 注册监听键盘按键
     */
    registerKeyDownAndUp () {
      let _this = this;

      $(document).unbind('keydown');
      $(document).unbind('keyup');

      this.registerKeyCtrlAndS();

      $(document).bind("keydown", function(e) {

        let keyCode = event.keyCode || event.which || event.charCode;
        let ctrlKey = event.ctrlKey || event.metaKey;

        // 快捷删除，mac下为cmd+backspace，windows下为delete键
        if ((ctrlKey && keyCode == 8) || keyCode == 46) {
          event.preventDefault();
          _this.$DesignerCommonUtil.backspaceDeleteLayoutOrGroupItem(
              _this.currentSelectLayoutItemId, _this.currentSelectLayoutItemIds, _this.currentSelectGroupItemId, _this.currentSelectGroupItemIds)
        }

        // ctrl + z 回退、撤销操作
        if (ctrlKey && keyCode == 90) {
          event.preventDefault();
          _this.$store.dispatch('designer/stepBackward');
        }

        // ctrl + y 单步恢复
        if (ctrlKey && keyCode == 89) {
          event.preventDefault();
          _this.$store.dispatch('designer/stepRecover');
        }

        // 解决windows系统下，keydown一直触发的问题
        if (_this.keydownFlag) {
          return
        }
        _this.keydownFlag = true;

        if(_this.$PnUtil.isMac()) {
          if(ctrlKey) { // Command键
            _this.$store.commit('designer/setKeepCtrl', true)
            if(_this.tmpCurrentSelectLayoutItemId) {
              let tmpIds = _this.currentSelectLayoutItemIds.concat();
              tmpIds.pushNoRepeat(_this.tmpCurrentSelectLayoutItemId);
              _this.$store.commit('designer/setCurrentSelectLayoutItemIds', tmpIds)
            }
            if(_this.tmpCurrentSelectGroupItemId) {
              let tmpIds = _this.currentSelectGroupItemIds.concat();
              tmpIds.pushNoRepeat(_this.tmpCurrentSelectGroupItemId);
              _this.$store.commit('designer/setCurrentSelectGroupItemIds', tmpIds)
            }
          }
          if(e.keyCode == 18) {
            _this.enableLayoutItemSelectable()
          }
        }else if(_this.$PnUtil.isWindows()) {
          if(ctrlKey) { // Ctrl键
            _this.$store.commit('designer/setKeepCtrl', true)
            if(_this.tmpCurrentSelectLayoutItemId) {
              let tmpIds = _this.currentSelectLayoutItemIds.concat();
              tmpIds.pushNoRepeat(_this.tmpCurrentSelectLayoutItemId);
              _this.$store.commit('designer/setCurrentSelectLayoutItemIds', tmpIds)
            }
            if(_this.tmpCurrentSelectGroupItemId) {
              let tmpIds = _this.currentSelectGroupItemIds.concat();
              tmpIds.pushNoRepeat(_this.tmpCurrentSelectGroupItemId);
              _this.$store.commit('designer/setCurrentSelectGroupItemIds', tmpIds)
            }
          }
          if(e.keyCode == 18) {
            _this.enableLayoutItemSelectable()
          }
        }

        if (e.keyCode == 16) {
          _this.enableGroupItemSelectable()
        }

        if (e.keyCode == 37) { // 方向左键
          // 判断如果当前移动的是组，那么就不需要再执行moveLayoutItem
          if (_this.currentSelectGroupItemId || _this.currentSelectGroupItemIds.length > 0) {
            _this.currentSelectGroupItemLocation = _this.$DesignerCommonUtil.directionKeyMoveGroupItem(
                'left', _this.currentSelectGroupItemId, _this.currentSelectGroupItemIds, _this.layout, _this.currentSelectGroupItemLocation)
          }else {
            _this.$DesignerCommonUtil.directionKeyMoveLayoutItem(
                'left', _this.tmpCurrentSelectLayoutItemId, _this.currentSelectLayoutItemIds, _this.layout, _this.layoutGroup);
          }
          e.preventDefault()
        }
        else if(e.keyCode == 38) { // 方向上键
          if (_this.currentSelectGroupItemId || _this.currentSelectGroupItemIds.length > 0) {
            _this.currentSelectGroupItemLocation = _this.$DesignerCommonUtil.directionKeyMoveGroupItem(
                'top', _this.currentSelectGroupItemId, _this.currentSelectGroupItemIds, _this.layout, _this.currentSelectGroupItemLocation)
          }else {
            _this.$DesignerCommonUtil.directionKeyMoveLayoutItem(
                'top', _this.tmpCurrentSelectLayoutItemId, _this.currentSelectLayoutItemIds, _this.layout, _this.layoutGroup);
          }
          e.preventDefault()
        }
        else if(e.keyCode == 39) { // 方向右键
          if (_this.currentSelectGroupItemId || _this.currentSelectGroupItemIds.length > 0) {
            _this.currentSelectGroupItemLocation = _this.$DesignerCommonUtil.directionKeyMoveGroupItem(
                'right', _this.currentSelectGroupItemId, _this.currentSelectGroupItemIds, _this.layout, _this.currentSelectGroupItemLocation)
          }else {
            _this.$DesignerCommonUtil.directionKeyMoveLayoutItem(
                'right', _this.tmpCurrentSelectLayoutItemId, _this.currentSelectLayoutItemIds, _this.layout, _this.layoutGroup);
          }
          e.preventDefault()
        }
        else if(e.keyCode == 40) { // 方向下键
          if (_this.currentSelectGroupItemId || _this.currentSelectGroupItemIds.length > 0) {
            _this.currentSelectGroupItemLocation = _this.$DesignerCommonUtil.directionKeyMoveGroupItem(
                'bottom', _this.currentSelectGroupItemId, _this.currentSelectGroupItemIds, _this.layout, _this.currentSelectGroupItemLocation)
          }else {
            _this.$DesignerCommonUtil.directionKeyMoveLayoutItem(
                'bottom', _this.tmpCurrentSelectLayoutItemId, _this.currentSelectLayoutItemIds, _this.layout, _this.layoutGroup);
          }
          e.preventDefault()
        }

      });
      $(document).bind("keyup", function(e) {
        _this.keydownFlag = false;
        if(_this.$PnUtil.isMac()) {
          if(e.keyCode == 91) { // Command键
            _this.$store.commit('designer/setKeepCtrl', false)
          }
          if (e.keyCode == 93) {
            _this.$store.commit('designer/setKeepCtrl', false)
          }
          if(e.keyCode == 18) {
            _this.disableSelectable()
          }
        }else if(_this.$PnUtil.isWindows()) {
          if(e.keyCode == 17) { // Ctrl键
            _this.$store.commit('designer/setKeepCtrl', false)
          }
          if(e.keyCode == 18) {
            _this.disableSelectable()
          }
        }
        if(e.keyCode == 16) {
          _this.disableSelectable()
        }
      });

    },

    /**
     * 注册画布放置监听
     */
    registerCanvasDrop () {
      let _this = this;

      // 计算鼠标在画布中的左偏移与右偏移
      let calculateMouseLeftAndTop = (e, direction) => {
        switch (direction) {
          case 'left':
            return Math.ceil((e.pageX - $("#AbsoluteLayout").offset().left)/this.zoomValue);
          case 'top':
            return Math.ceil((e.pageY - $("#AbsoluteLayout").offset().top)/this.zoomValue);
          default:
            return 0
        }
      };

      $("#AbsoluteLayout").droppable({
        accept: ".comp-card",
        drop: (e, ui) => {
          let compName = ui.draggable[0].attributes['data-component'].nodeValue;
          let baseAttr = _this.$PnUtil.getCompBaseAttr(compName);

          // 判断是否放置的是布局块组件
          if (compName == 'DefaultLayoutItem') {
            let newLayoutItem = this.$DesignerCommonUtil.buildAbsoluteLayoutItem();
            newLayoutItem.layoutItemConfigData.left = calculateMouseLeftAndTop(e, 'left');
            newLayoutItem.layoutItemConfigData.top = calculateMouseLeftAndTop(e, 'top');
            _this.$store.commit('designer/addLayoutItem', newLayoutItem);
            _this.$store.commit('designer/setCurrentSelectLayoutItemId', newLayoutItem.id);
          }else {

            // 如果data-id不等于空，则为收藏的组件
            if (ui.draggable[0].attributes['data-id']) {

              let id = ui.draggable[0].attributes['data-id'].nodeValue;
              this.$PnApi.EnshrineCompApi.getLayoutItemObjById(id).then(result => {
                let newLayoutItem = JSON.parse(result.data.payload);
                let type = ui.draggable[0].attributes['data-type'].nodeValue;
                // 如果type='F'说明收藏的是普通功能组件
                if (type && type == 'F') {
                  newLayoutItem.id = _this.$PnUtil.uuid();
                  if (newLayoutItem.component.id) {
                    newLayoutItem.component.id = this.$PnUtil.uuid()
                  }
                  newLayoutItem.layoutItemConfigData.left = calculateMouseLeftAndTop(e, 'left');
                  newLayoutItem.layoutItemConfigData.top = calculateMouseLeftAndTop(e, 'top');
                  _this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');
                  _this.$store.commit('designer/addLayoutItem', newLayoutItem);
                  _this.$store.commit('designer/setCurrentSelectLayoutItemId', newLayoutItem.id);
                  if (newLayoutItem.component.id) {
                    _this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', newLayoutItem.component.name + 'Form');
                  }
                }
                // 如果type='G'说明收藏的是组
                else if (type && type == 'G') {
                  let groupItem = newLayoutItem.groupItemObj;
                  let layoutItems = newLayoutItem.layoutItemObjs;
                  // 记录所有布局块基于组坐标的偏移位置
                  let offsetInfoArr = [];
                  // 组在收藏时保存的坐标位置
                  let groupItemOriginalPosition = {
                    left: groupItem.groupItemConfigData.left,
                    top: groupItem.groupItemConfigData.top
                  };
                  // 遍历被收藏的组关联的所有布局块，然后记录各自基于组原始坐标的位置偏移
                  layoutItems.forEach(layoutItem => {
                    let offsetInfo = {
                      layoutItemId: layoutItem.id,
                      offsetLeft: layoutItem.layoutItemConfigData.left - groupItemOriginalPosition.left,
                      offsetTop: layoutItem.layoutItemConfigData.top - groupItemOriginalPosition.top
                    };
                    offsetInfoArr.push(offsetInfo)
                  });

                  let newLayoutItemIds = [];
                  let newGroupItem = groupItem;
                  newGroupItem.groupItemConfigData.left = calculateMouseLeftAndTop(e, 'left');
                  newGroupItem.groupItemConfigData.top = calculateMouseLeftAndTop(e, 'top');
                  layoutItems.forEach(layoutItem => {
                    let offsetInfo = _.find(offsetInfoArr, {layoutItemId: layoutItem.id});
                    layoutItem.layoutItemConfigData.left = newGroupItem.groupItemConfigData.left + offsetInfo.offsetLeft;
                    layoutItem.layoutItemConfigData.top = newGroupItem.groupItemConfigData.top + offsetInfo.offsetTop;
                    let newId = _this.$PnUtil.uuid();
                    newLayoutItemIds.push(newId);
                    layoutItem.id = newId;
                    if (layoutItem.component.id) {
                      layoutItem.component.id = _this.$PnUtil.uuid()
                    }
                    _this.$store.commit('designer/addLayoutItem', layoutItem);
                  });

                  newGroupItem.id = _this.$PnUtil.uuid();
                  newGroupItem.layoutItemIds = newLayoutItemIds;
                  _this.$store.commit('designer/addLayoutGroupItem', newGroupItem);
                  _this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');
                  _this.$store.commit('designer/setCurrentSelectGroupItemId', newGroupItem.id);
                }
              })

            }else {
              let newLayoutItem = _this.$DesignerCommonUtil.buildAbsoluteLayoutItem();
              newLayoutItem.layoutItemConfigData.left = calculateMouseLeftAndTop(e, 'left');
              newLayoutItem.layoutItemConfigData.top = calculateMouseLeftAndTop(e, 'top');

              let component = {
                id: _this.$PnUtil.uuid(),
                name: compName,
                version: baseAttr.version,
                compConfigData: Object.assign({}, _this.$PnUtil.deepClone(_this.$PnUtil.getCompConfigData(compName)))
              };

              newLayoutItem.component = component;

              _this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');
              _this.$store.commit('designer/addLayoutItem', newLayoutItem);
              _this.$store.commit('designer/setCurrentSelectLayoutItemId', newLayoutItem.id);
              if (newLayoutItem.component.id) {
                _this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', newLayoutItem.component.name + 'Form');
              }
            }

          }

        }
      });
    },

    /**
     * 注册布局块放置监听
     */
    registerLayoutItemDrop() {
      let _this = this;

      // 必须设置延迟，否则将无法正常给动态新增的布局块添加拖拽等事件
      setTimeout(() => {

        // 注册布局块放置监听
        $(".absolute-layout-item").droppable({
          accept: ".comp-card",
          // activeClass: "layout-item-drop-active",
          // hoverClass: "layout-item-drop-hover",
          drop: (e, ui) => {

            let layoutItemId = e.target.attributes['data-id'].nodeValue;
            let compName = ui.draggable[0].attributes['data-component'].nodeValue;
            let baseAttr = _this.$PnUtil.getCompBaseAttr(compName);

            if (compName == 'DefaultLayoutItem') {
              _this.$Message.warning('布局块不可多层嵌套！')
            }else {
              let addComponent = function (_layoutItemId) {
                let component = {
                  id: _this.$PnUtil.uuid(),
                  name: compName,
                  version: baseAttr.version,
                  compConfigData: Object.assign({}, _this.$PnUtil.deepClone(_this.$PnUtil.getCompConfigData(compName)))
                };

                _this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');
                _this.$store.commit('designer/addComponentToLayoutItem', {
                  layoutItemId: _layoutItemId,
                  component: component
                })
                _this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', component.name + 'Form');
              };

              // 如果data-id不等于空，则为收藏的组件
              if (ui.draggable[0].attributes['data-id']) {
                _this.$Message.warning({
                  content: '收藏的组件不可以替换布局块原本绑定的组件',
                  duration: 3
                })
              }else {
                let storeLayoutItem = this.$store.getters['designer/getLayoutItemById'](layoutItemId);
                if (storeLayoutItem.component.id) {
                  this.$Modal.confirm({
                    title: '提醒',
                    content: '目标布局块已关联组件，是否要覆盖？',
                    okText: '覆盖',
                    onOk: () => {
                      addComponent(layoutItemId)
                    }
                  })
                }else {
                  addComponent(layoutItemId)
                }
              }

            }

          }
        });

      }, 100);

    },

    /**
     * 画布右键事件处理
     **/
    onLayoutCanvasRightClickHandler (e) {
      e.preventDefault();
      this.$EventBus.$emit('pn_showLayoutCanvasContextmenu', e)
    },

    layoutCanvasContextmenuClick (name) {
      switch (name) {
        case 'layoutCanvasMenu_clearCanvas':
          this.$DesignerCommonUtil.clearCanvas();
          break;
        case 'layoutCanvasMenu_pasteShearPlateData':
          this.$DesignerCommonUtil.pasteShearPlateData();
          break;
        case 'layoutCanvasMenu_pasteShearPlateDataRetainLocation':
          this.$DesignerCommonUtil.pasteShearPlateData(true);
          break;
        case 'layoutCanvasMenu_logoutKeyDownAndUp':
          $(document).unbind('keydown');
          $(document).unbind('keyup');
          this.$store.commit('designer/setKeepCtrl', false);
          this.$Message.success('键盘事件已注销')
          break;
      }
    },

    /**
     * 画布点击事件监听
     */
    layoutCanvasClick () {
      // console.log('layoutCanvasClick');

      this.$refs.layoutCanvasContextmenu.hide();

      // 设置画布激活状态为true
      this.$store.commit('designer/setCanvasEnabled', true);

      // 清空所有布局块的scope，然后给画布的放置配置设置scope为compCardScope
      $('.absolute-layout-item').droppable('option', 'scope', '');
      this.$AbsoluteLayout.droppable('option', 'scope', 'compCardScope');

      if (!this.tmpCurrentSelectLayoutItemId && !this.keepSelectable) {
        this.registerKeyDownAndUp(); // 重新注册键盘监听

        this.$store.commit('designer/setRightSidebarFuncCompConfigFormName', '');
        this.$store.commit('designer/setCurrentSelectLayoutItemId', '');
        this.$store.commit('designer/setCurrentSelectLayoutItemIds', []);
      }
      if (!this.tmpCurrentSelectGroupItemId && !this.keepSelectable) {
        this.registerKeyDownAndUp(); // 重新注册键盘监听

        this.$store.commit('designer/setCurrentSelectGroupItemId', '');
        this.$store.commit('designer/setCurrentSelectGroupItemIds', []);
        this.groupItemEditable = false;
      }
    },

    /**
     * 布局块点击事件监听
     * @param layoutItem
     * @param event
     */
    layoutItemClick(layoutItem, event) {
      // 设置画布激活状态为false
      this.$store.commit('designer/setCanvasEnabled', false);

      this.$refs.contextmenu.hide();
      this.$refs.layoutCanvasContextmenu.hide();

      // 判断当前是否按住了ctrl按键 或 alt按键
      if(this.$store.getters['designer/getKeepCtrl'] || this.keepSelectable) {
        let selectLayoutItemIds = this.currentSelectLayoutItemIds.concat();

        if(selectLayoutItemIds.indexOf(layoutItem.id) > -1) {
          for (let i=0; i<selectLayoutItemIds.length; i++) {
            if(layoutItem.id == selectLayoutItemIds[i]) {
              if(selectLayoutItemIds.length > 1) {
                selectLayoutItemIds.splice(i, 1);
                i--
              }
            }
          }
        }else {
          selectLayoutItemIds.pushNoRepeat(layoutItem.id);
        }
        this.$store.commit('designer/setCurrentSelectLayoutItemIds', selectLayoutItemIds);
      } else {
        if(this.currentSelectLayoutItemIds.indexOf(layoutItem.id) == -1) {
          this.$store.commit('designer/setCurrentSelectLayoutItemIds', []) // 清除ctrl选中的布局块
        }
      }

      this.$store.commit('designer/setCurrentSelectGroupItemId', '');
      this.$store.commit('designer/setCurrentSelectGroupItemIds', []);
    },

    buildLayoutClassObj (layout) {
      let clazz = '';

      return clazz
    },

    buildGroupItemActiveClass (groupItem) {
      if (this.currentSelectGroupItemIds.length > 0) {
        if (this.currentSelectGroupItemIds.indexOf(groupItem.id) > -1) {
          return 'active'
        }else {
          return ''
        }
      }else {
        if (this.currentSelectGroupItemId == groupItem.id) {
          return 'active'
        }
      }

      if (this.currentHoverGroupItemId == groupItem.id) {
        return 'active'
      }

      return ''
    }
  },
  computed: {
    ...mapFields({
      layout: 'pageMetadata.layout',
      layoutGroup: 'pageMetadata.layout.layoutGroup',
      currentSelectGroupItemId: 'currentSelectGroupItemId',
      currentSelectGroupItemIds: 'currentSelectGroupItemIds',
      currentHoverGroupItemId: 'currentHoverGroupItemId',
      canvasEnabled: 'canvasEnabled',
      canvasMapCollapsed: 'canvasMapCollapsed',
      pageLinesData: 'pageLinesData',
      alongShowTargetIdList: 'alongShowTargetIdList',
      isAlongCompEditModel: 'isAlongCompEditModel'
    }),
    absoluteLayoutCanvasStyleObject () {
      return {
        '--layout-item-active-outline-width': (1 * 1/this.zoomValue) + 'px',
        '--drag-handle-border-width': (1 * 1/this.zoomValue) + 'px',
        '--drag-handle-width': (8 * 1/this.zoomValue) + 'px',
        '--drag-handle-height': (8 * 1/this.zoomValue) + 'px',
        '--drag-handle-offset': -(4 * 1/this.zoomValue) + 'px',
      }
    }
  },
  watch: {
    'layout.layoutItems': {
      handler: 'registerLayoutItemDrop'
    },
    'currentSelectLayoutItemId': {
      handler: function (val) {
        if (val) {
          // 点击布局块的时候，清空画布的scope，然后给布局块设置droppable的属性scope为compCardScope，
          // 与组件库拖拽对象的scope对应，这样组件库的拖拽对象就可以放置在当前点击的布局块里
          this.$AbsoluteLayout.droppable('option', 'scope', '');
          $('.absolute-layout-item').droppable('option', 'scope', '');
          $('#'+val).droppable('option', 'scope', 'compCardScope');
          if (this.canvasEnabled) {
            // 设置画布激活状态为false
            this.$store.commit('designer/setCanvasEnabled', false);
          }
        }
      }
    },
    // 监听画布是否被激活状态
    'canvasEnabled': {
      handler: function (val) {
        if (val) {
          // 清空所有布局块的scope，然后给画布的放置配置设置scope为compCardScope
          $('.absolute-layout-item').droppable('option', 'scope', '');
          this.$AbsoluteLayout.droppable('option', 'scope', 'compCardScope');
        }
      }
    },
    'zoomValue': {
      handler: function (val) {
        if (val < 1) {
          $('#zoomArea').scrollLeft(0).scrollTop(0);
        }
      }
    }
  },
  filters: {
    layoutItemAliasNameFilter (layoutItem) {
      if (layoutItem.component.id) {
        return layoutItem.aliasName ? layoutItem.aliasName : JSON.parse(localStorage.getItem('allCompinfoObj'))[layoutItem.component.name].alias_name
      }else {
        return '未绑定组件布局块'
      }
    }
  }
}
</script>

<style lang="less" scoped>

.canvas-toolbar {
  width: 100%;
  height: 33px;
  border-bottom: 1px solid #424242;
  background-color: #616161;
  position: fixed;
  top: 48px;
  z-index: 3;
  line-height: 30px;
  padding-left: 20px;
}

.absolute-layout-container {
  width: 100%;
  height: calc(100% - 33px);
  overflow: auto;
  margin-top: 33px;
}

.absolute-layout-canvas {
  position: relative;
  box-shadow: rgba(0,0,0,.5) 0 0 30px 0;
}

.absolute-layout-item {
  position: absolute;
  width: 100%;
  height: 100%;
  &.active {
    box-shadow: 0 0 10px #FFF;
    outline: var(--layout-item-active-outline-width) solid #4AFFFF;
  }
  &.ui-selecting {
    outline: var(--layout-item-active-outline-width) solid #4AFFFF;
  }
}

.ivu-cell i {
  font-size: 16px;
  margin-top: -2px;
}

/* 组相关样式 */
.group-item {
  border: var(--layout-item-active-outline-width) dashed #fff;
  cursor: move;
}

.group-item-child {
  &.active {
    outline: var(--layout-item-active-outline-width) solid #fb8c00;
  }
  &.ui-selecting {
    outline: var(--layout-item-active-outline-width) solid #fb8c00;
  }
  .lock-icon {
    position: absolute;
    right: 1px;
    top: 0px;
    color: #fff;
  }
}

/* 画布映射层样式 */
#canvas_map {
  position: absolute;
  bottom: 10px;
  right: 10px;
  width: 180px;
  height: 100%;
  z-index: 9999;
  border: 2px solid #2979ff;
  /*transition: all 0.2s ease-in-out 0s*/
}
</style>
